package org.rc.web;

import com.google.appengine.api.blobstore.BlobInfoFactory;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.*;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.rc.dao.GenericDao;
import org.rc.model.ResultsFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This servlet will be responsible for uploading a file of results and store in the blobstore and associated metadata in the datastore.
 * This will not process the results. That will be done on a TaskQueue
 * @author dokeeffe
 */
public class UploadServlet extends IndexServlet {

    private static final Logger LOGGER = LoggerFactory.getLogger(UploadServlet.class);
    private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
    private final BlobInfoFactory blobInfoFactory = new BlobInfoFactory();
    private GenericDao<ResultsFile> resultsFileDao = new GenericDao<ResultsFile>(ResultsFile.class);

    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        if (request.getParameter("action")!=null) {
            processActions(request,response);
        } else {
            //Its an upload, upload the file to the blobstore
            Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(request);
            BlobKey blobKey = blobs.get("myFile");
            uploadFile(blobKey, response);
        }
    }

    /**
     * Show the uploads page
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
        
        //show list of uploaded
        Collection<ResultsFile> files = resultsFileDao.getAll();
        request.setAttribute("uploads", files);
        forward(request, response, "upload.jsp");
    }

    /**
     * Process the results file by sending it to the task queue
     * @param request
     * @param response
     * @throws IOException
     */
    private void processFileOnQueue(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String id = request.getParameter("id");
        if (id != null) {
            Queue queue = QueueFactory.getDefaultQueue();
            queue.add(withUrl("/parse?id=" + id + "&from=1").method(Method.GET));
            response.sendRedirect("/upload");
        }
    }

    private void uploadFile(BlobKey blobKey, HttpServletResponse response) throws IOException {
        Objectify ofy = ObjectifyService.begin();
        ResultsFile rf = new ResultsFile();
        rf.setName(blobInfoFactory.loadBlobInfo(blobKey).getFilename());
        rf.setDateUploaded(new Date());
        rf.setBlobKey(blobKey.getKeyString());
        ofy.put(rf);
        response.sendRedirect("/upload");
    }

    /**
     * Process actions from the upload area (delete)
     * @param request
     * @param response
     */
    private void processActions(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String action = request.getParameter("action");
        LOGGER.debug("handling action: " + action);
        if("delete".equals(action)) {
            Long id= new Long(request.getParameter("id"));
            response.sendRedirect("/upload");
        } else if("parse".equals(action)) {
            processFileOnQueue(request, response);
        }
    }
}
